<!doctype html>
<html>
    <head>
        <title>动画手册 - HT for Web</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="user-scalable=yes, width=1024">
        <style type="text/css">
            h1, h2, h3, h4, h5, h6, p, blockquote {
                margin: 0;
                padding: 0;
            }
            body {
                font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif;
                font-size: 13px;
                line-height: 18px;
                color: #737373;
                background-color: white;
                margin: 10px 13px 10px 13px;
            }
            table {
                margin: 10px 0 15px 0;
                border-collapse: collapse;
            }
            td,th {
                border: 1px solid #ddd;
                padding: 3px 10px;
            }
            th {
                padding: 5px 10px;
            }
            a {
                color: #0069d6;
            }
            a:hover {
                color: #0050a3;
                text-decoration: none;
            }
            a img {
                border: none;
            }
            p {
                margin-bottom: 9px;
            }
            h1, h2, h3, h4, h5, h6 {
                color: #404040;
                line-height: 36px;
            }
            h1 {
                margin-bottom: 18px;
                font-size: 30px;
            }
            h2 {
                font-size: 24px;
            }
            h3 {
                font-size: 18px;
            }
            h4 {
                font-size: 16px;
            }
            h5 {
                font-size: 14px;
            }
            h6 {
                font-size: 13px;
            }
            hr {
                margin: 0 0 19px;
                border: 0;
                border-bottom: 1px solid #ccc;
            }
            blockquote {
                padding: 13px 13px 21px 15px;
                margin-bottom: 18px;
                font-family:georgia,serif;
                font-style: italic;
            }
            blockquote:before {
                content:"\201C";
                font-size:40px;
                margin-left:-10px;
                font-family:georgia,serif;
                color:#eee;
            }
            blockquote p {
                font-size: 14px;
                font-weight: 300;
                line-height: 18px;
                margin-bottom: 0;
                font-style: italic;
            }
            code, pre {
                font-family: Monaco, Andale Mono, Courier New, monospace;
            }
            code {
                background-color: #fee9cc;
                color: rgba(0, 0, 0, 0.75);
                padding: 1px 3px;
                font-size: 12px;
                border-radius: 3px;
            }
            pre {
                display: block;
                padding: 14px;
                margin: 0 0 18px;
                line-height: 16px;
                font-size: 11px;
                border: 1px solid #d9d9d9;
                white-space: pre-wrap;
                word-wrap: break-word;
            }
            pre code {
                background-color: #fff;
                color:#737373;
                font-size: 11px;
                padding: 0;
            }
            sup {
                font-size: 0.83em;
                vertical-align: super;
                line-height: 0;
            }
            * {
                -webkit-print-color-adjust: exact;
            }
            @media screen and (min-width: 914px) {
                body {
                    width: 854px;
                    margin:10px auto;
                }
            }
            @media print {
                body,code,pre code,h1,h2,h3,h4,h5,h6 {
                    color: black;
                }
                table, pre {
                    page-break-inside: avoid;
                }
            }
            iframe{
                width: 100%;
                border: 1px solid #34495E;
                margin: 0;
            }
            .logo{
                vertical-align: middle;
            }

        </style>
        <script>
            function init() {
                var logoSrc = '',
                    logos = document.querySelectorAll('.logo'),
                    i = 0;
                for (; i < logos.length; i++) {
                    logos[i].src = logoSrc;
                }

                var iframes = document.querySelectorAll('iframe'),
                    func = function(){};
                for (i=0; i < iframes.length; i++) {
                    var iframe = iframes[i];

                    // a small hack to make it work on android
                    iframe.ontouchstart = func;

                    if (window.location && window.location.hostname && window.location.hostname.indexOf('hightopo') >= 0) {
                        var div = document.createElement('div');
                        div.style.float = 'left';
                        div.innerHTML = '<a href="https://hightopo.com/codeeditor/index.html?url=' + iframe.contentWindow.location.pathname + '" target="_blank">在线编辑</a>';
                        iframe.parentNode.insertBefore(div, iframe);

                        var div = document.createElement('div');
                        div.style.float = 'left';
                        div.innerHTML = '&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;';
                        iframe.parentNode.insertBefore(div, iframe);
                    }

                    var div = document.createElement('div');
                    div.innerHTML = '<a href="' + iframe.src + '" target="_blank">独立运行→</a>';
                    iframe.parentNode.insertBefore(div, iframe);
                }
            }
        </script>
    </head>
    <body onload="init();">
        <a href="http://www.hightopo.com"><img class="logo"></a>HT 动画手册
        <hr style="margin: 1px 0 20px 0">
<p>索引</p>

<ul><li><a href="#ref_description">概述</a></li><li><a href="#ref_demo1">示例一</a></li><li><a href="#ref_demo2">示例二</a></li><li><a href="#ref_demo3">示例三</a></li><li><a href="#ref_demo4">示例四</a></li></ul>

<hr/>

<div id="ref_description"></div>

<h3>概述</h3>

<p><code>HT</code>系统可通过<a href="../../core/beginners/ht-beginners-guide.html#ref_animation">入门手册</a>介绍的<code>ht.Default.startAnim</code>函数，
或者<a href="../../core/schedule/ht-schedule-guide.html">调度手册</a>介绍的<code>DataModel#addScheduleTask</code>函数，动态改变模型属性以达到动画效果。
本手册将要介绍的动画插件则更进一步对动画进行封装，用户只需用描述性的说明<code>HT</code>即可自动实现动画过程，动画插件可以将图元的一个或多个属性值
(如<code>width</code>、<code>height</code>、<code>opacity</code>等)从一个值平滑的缓动至另一个值，同时提供了丰富的缓动方式用于实现各种效果，如闪烁、跳跃、变色等。</p>

<p>使用此插件之前，需要引入<code>ht-animation.js</code>文件：</p>

<pre><code>&lt;script src=&quot;ht.js&quot;&gt;&lt;/script&gt; &lt;!--先引入ht.js--&gt;
&lt;script src=&quot;ht-animation.js&quot;&gt;&lt;/script&gt;</code></pre>

<p>要使用动画，首先您需要调用<code>ht.DataModel#enableAnimation(interval)</code>启动全局动画定时器，参数<code>interval</code>指定全局动画间隔，默认为<code>requestAnimFrame</code>的时间(<code>16ms</code>左右，因浏览器而异)，
也就是说，如果不指定<code>interval</code>参数，<code>DataModel</code>定时器每隔<code>16ms</code>左右就会遍历自己所有的<code>Data</code>，根据<code>Data</code>的<code>animation</code>配置执行动画</p>

<p>除了<code>enableAnimation</code>，<code>DataModel</code>上还有另外两个<code>API</code>经常用到：</p>

<ul><li><code>disableAnimation()</code> 停止全局动画定时器，如果不需要动画请关闭定时器，不然会造成性能浪费</li><li><code>getDataAnimation(data)</code> 获得参数<code>data</code>的动画配置，如果不想为每个<code>Data</code>指定<code>animation</code>参数，而是希望根据<code>Data</code>种类或标识生成动画配置，
可以重写此方法实现(参考示例二)</li></ul>

<p>此插件在<code>ht.Data</code>上扩展了一个<code>setAnimation(config)</code>方法用于配置当前图元的动画设置，一个简单的配置示例如下：</p>

<pre><code>data.setAnimation({
    show: {
        property: &quot;opacity&quot;,
        accessType: &quot;style&quot;, 
        from: 1, 
        to: 0,
        repeat: true
    },
    start: [&quot;show&quot;]
});</code></pre>

<p>可以看到，参数<code>config</code>是一个<code>js</code>对象，在这个对象里除了<code>start</code>有特殊含义，您可以使用任意字符串定义一个或多个动画过程</p>

<p>上面的配置中，定义了一个名为<code>show</code>的动画过程，这个动画过程改变图元的<code>opacity</code>样式(透明度)，将其从<code>1</code>变化至<code>0</code>，<code>repeat</code>表示动画一直会重复，直到您调用<code>setAnimation(null)</code>
清除动画。需要注意：</p>

<pre><code>通过API清除动画后，属性可能处于任何状态，如上面的例子，opaciy样式可能是0-1之间的任何数字，您可能需要重设此样式。</code></pre>

<p><code>start</code>是一个数组，用于指定要启动的一个或多个动画，上面的例子里只定义了一个名为<code>show</code>的动画，事实上，您可以定义任意多个，动画的配置参数列举如下：</p>

<ul><li><code>property</code> 动画要改变的图元的属性名</li><li><code>accessType</code> <code>property</code>的类型，枚举如下：<ul><li><code>null</code> 默认类型，如<code>property</code>为<code>width</code>，采用<code>getWidth()</code>和<code>setWidth(value)</code>的<code>get/set</code>或<code>is/set</code>方式存取。</li><li><code>style</code> 如<code>property</code>为<code>width</code>，采用<code>getStyle(&#39;width&#39;)</code>和<code>setStyle(&#39;width&#39;, value)</code>的方式存取。</li><li><code>attr</code> 如<code>property</code>为<code>width</code>，采用<code>getAttr(&#39;width&#39;)</code>和<code>setAttr(&#39;width&#39;, value)</code>的方式存取。</li></ul></li><li><code>from</code> 动画开始时的属性值</li><li><code>to</code> 动画结束时的属性值</li><li><code>frames</code> 动画帧数，默认为<code>60</code></li><li><code>duration</code> 持续时间，单位 <code>ms</code>；<code>frames</code> 和此参数只能选择一个，不可同时存在</li><li><code>interval</code> 动画间隔，单位<code>ms</code>，如果不指定等同于全局动画间隔;适用于当前图元的动画间隔与全局动画间隔不一致的情况</li><li><code>delay</code> 动画延迟执行时间，单位<code>ms</code></li><li><code>repeat</code> 指定动画是否循环执行，如果为数字，表示循环的次数</li><li><p><code>easing</code> 动画方式，枚举如下：<code>Linear、Quad.easeIn、Quad.easeOut、 Quad.easeInOut;Cubic.easeIn、Cubic.easeOut、 Cubic.easeInOut;
Quart.easeIn、Quart.easeOut、 Quart.easeInOut;Quint.easeIn、Quint.easeOut、 Quint.easeInOut;Sine.easeIn、Sine.easeOut、 Sine.easeInOut;
Expo.easeIn、Expo.easeOut、 Expo.easeInOut;Circ.easeIn、Circ.easeOut、 Circ.easeInOut;Elastic.easeIn、Elastic.easeOut、 Elastic.easeInOut;
Back.easeIn、Back.easeOut、 Back.easeInOut;Bounce.easeIn、Bounce.easeOut、 Bounce.easeInOut</code></p><p>这些动画方式有何区别？参考这里：<a href="http://easings.net/">http://easings.net/</a></p></li><li><p><code>onUpdate: function(value)</code> 回调函数，动画的每一帧都会回调此函数。</p></li><li><code>onComplete: function()</code> 回调函数，动画完成后执行</li><li><code>next</code> 字符串类型，指定当前动画完成之后，要执行的下个动画，可将多个动画融合</li></ul>

<p><code>ht.Data</code> 上支持下面的函数用于暂停和继续动画：</p>

<ul><li><code>pauseAnimation()</code> 暂停动画</li><li><code>resumeAnimation()</code> 继续动画</li></ul>

<div id="ref_demo1"></div>

<h3>示例一</h3>

<p><iframe src="examples/example_demo1.html" style="height:400px"></iframe></p>

<p>需要注意染色图元的配置：</p>

<pre><code>node2.setAnimation({
    blend: {
        from: 255, 
        to: 0,
        next: &quot;clear&quot;,
        onUpdate: function(value) {
            value = parseInt(value);
            this.s(&quot;body.color&quot;, &quot;rgb(255, &quot; + value + &quot;, &quot; + value + &quot;)&quot;);
        }
    },
    clear: {
        from: 0, 
        to: 255,
        next: &quot;blend&quot;,
        onUpdate: function(value) {
            value = parseInt(value);
            this.s(&quot;body.color&quot;, &quot;rgb(255, &quot; + value + &quot;, &quot; + value + &quot;)&quot;);
        }
    },
    start: [&quot;blend&quot;]
});</code></pre>

<p><code>start</code>参数指定了从<code>blend</code>动画开始执行，染色动画实际一直在改变图元的<code>body.color</code>样式，这里我们没有指定<code>property</code>和<code>accessType</code>，因为
<code>body.color</code>不是单纯的数字类型，而是一个表示<code>RGB</code>颜色的字符串，所以我们用到了<code>onUpdate</code>回调函数，每一帧都组合字符串改变图元的<code>body.color</code></p>

<div id="ref_demo2"></div>

<h3>示例二</h3>

<p><iframe src="examples/example_demo2.html" style="height:200px"></iframe></p>

<pre><code>dm.getDataAnimation = function(data) {
    if (data.getName() === &quot;node1&quot;) {
        if (data.getAnimation() != null) {
            return data.getAnimation();
        } else {
            return {
                hide: {
                    property: &quot;opacity&quot;,
                    accessType: &quot;style&quot;, 
                    from: 1, 
                    to: 0,
                    frames: 1,
                    next: &quot;show&quot;
                },
                show: {
                    property: &quot;opacity&quot;,
                    accessType: &quot;style&quot;, 
                    from: 0, 
                    to: 1,
                    frames: 1,
                    next: &quot;hide&quot;
                },
                start: [&quot;hide&quot;]
            };
        }
    } else {
        return null;
    }
};</code></pre>

<p>在这个例子里，我们没有调用<code>ht.Data#setAnimation</code>，而是通过重写<code>ht.DataModel#getDataAnimation</code>，根据图元的名字生成动画配置，
在某些要求灵活生成动画的场景下非常有用</p>

<div id="ref_demo3"></div>

<h3>示例三</h3>

<p>这个例子演示如何让虚线样式流动起来：</p>

<p><iframe src="examples/example_demo3.html" style="height:200px"></iframe></p>

<div id="ref_demo4"></div>

<h3>示例四</h3>

<p>这个例子演示如何让图元告警图标闪烁：</p>

<p><iframe src="examples/example_demo4.html" style="height:200px"></iframe></p>    <hr id="contact" style="margin: 20px 0 1px 0">
    <a href="http://www.hightopo.com"><img class="logo"></a>欢迎交流 <a href="mailto:service@hightopo.com">service@hightopo.com</a>
</body>
</html>
